package cn.cjj.gulimall.product.service.impl;

import cn.cjj.common.constant.ProductConstant;
import cn.cjj.common.to.SkuHasStockTo;
import cn.cjj.common.to.SkuReductionTo;
import cn.cjj.common.to.SpuBoundTo;
import cn.cjj.common.to.es.SkuEsModel;
import cn.cjj.common.utils.R;
import cn.cjj.gulimall.product.entity.*;
import cn.cjj.gulimall.product.feign.CouponFeignService;
import cn.cjj.gulimall.product.feign.SearchFeignService;
import cn.cjj.gulimall.product.feign.WareFeignService;
import cn.cjj.gulimall.product.service.*;
import cn.cjj.gulimall.product.vo.json.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cjj.common.utils.PageUtils;
import cn.cjj.common.utils.Query;

import cn.cjj.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;

    @Autowired
    SpuImagesService spuImagesService;

    @Autowired
    AttrService attrService;

    @Autowired
    ProductAttrValueService productAttrValueService;

    @Autowired
    SkuInfoService skuInfoService;

    @Autowired
    SkuImagesService skuImagesService;

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    CouponFeignService couponFeignService;

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    WareFeignService wareFeignService;

    @Autowired
    SearchFeignService searchFeignService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo spuSaveVo) {
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.saveBaseSpuInfo(spuInfoEntity);

        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        List<String> decript = spuSaveVo.getDecript();
        spuInfoDescEntity.setDecript(String.join(",", decript));
        this.saveSpuInfoDesc(spuInfoDescEntity);

        List<String> images = spuSaveVo.getImages();
        spuImagesService.saveImages(spuInfoDescEntity.getSpuId(), images);

        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(baseAttr -> {
            ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
            productAttrValueEntity.setAttrId(baseAttr.getAttrId());
            productAttrValueEntity.setAttrValue(baseAttr.getAttrValues());
            productAttrValueEntity.setQuickShow(baseAttr.getShowDesc());
            productAttrValueEntity.setSpuId(spuInfoEntity.getId());

            AttrEntity attrEntity = attrService.getById(baseAttr.getAttrId());
            productAttrValueEntity.setAttrName(attrEntity.getAttrName());

            return productAttrValueEntity;
        }).collect(Collectors.toList());
        productAttrValueService.saveProductAttr(productAttrValueEntities);

        List<Skus> skus = spuSaveVo.getSkus();

        skus.forEach(sku -> {
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            BeanUtils.copyProperties(sku, skuInfoEntity);

            skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
            skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
            skuInfoEntity.setSpuId(spuInfoEntity.getId());
            skuInfoEntity.setSaleCount(0L);
            sku.getImages().forEach(image -> {
                if (image.getDefaultImg() == 1) {
                    skuInfoEntity.setSkuDefaultImg(image.getImgUrl());
                }
            });
            skuInfoService.saveSkuInfo(skuInfoEntity);

            List<SkuImagesEntity> skuImageEntities = sku.getImages().stream().map(image -> {
                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                skuImagesEntity.setImgUrl(image.getImgUrl());
                skuImagesEntity.setDefaultImg(image.getDefaultImg());

                return skuImagesEntity;
            }).filter(entity -> {
                return StringUtils.isNotEmpty(entity.getImgUrl());
            }).collect(Collectors.toList());
            skuImagesService.saveSkuImages(skuImageEntities);

            List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = sku.getAttr().stream().map(attr -> {
                SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());

                return skuSaleAttrValueEntity;
            }).collect(Collectors.toList());
            skuSaleAttrValueService.saveSkuSaleAttrValue(skuSaleAttrValueEntities);

            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(sku, skuReductionTo);
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            if (skuReductionTo.getFullCount() > 0 ||
                    skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) > 0) {
                R r = couponFeignService.saveSkuReduction(skuReductionTo);
                if (r.getCode() != 0) {
                    log.error("远程调用couponFeignService.saveSkuReduction失败");
                }
            }
        });

        Bounds bounds = spuSaveVo.getBounds();
        SpuBoundTo spuBoundTo = new SpuBoundTo();
        BeanUtils.copyProperties(bounds, spuBoundTo);
        spuBoundTo.setSpuId(spuInfoEntity.getId());
        R r = couponFeignService.saveSpuBounds(spuBoundTo);
        if (r.getCode() != 0) {
            log.error("远程调用couponFeignService.saveSpuBounds失败");
        }
    }

    @Override
    public void saveBaseSpuInfo(SpuInfoEntity spuInfoEntity) {
        this.save(spuInfoEntity);
    }

    @Override
    public void saveSpuInfoDesc(SpuInfoDescEntity spuInfoDescEntity) {
        spuInfoDescService.save(spuInfoDescEntity);
    }

    //   page: 1,//当前页码
    //   limit: 10,//每页记录数
    //   sidx: 'id',//排序字段
    //   order: 'asc/desc',//排序方式
    //   key: '华为',//检索关键字
    //   catelogId: 6,//三级分类id
    //   brandId: 1,//品牌id
    //   status: 0,//商品状态
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)) {
            wrapper.and((w) -> {
                w.eq("id", key).or().like("spu_name", key);
            });
        }
        String catelogId = (String) params.get("catelogId");
        if (StringUtils.isNotEmpty(catelogId)) {
            if (!"0".equals(catelogId)) {
                wrapper.eq("catalog_id", catelogId);
            }
        }
        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotEmpty(brandId)) {
            if (!"0".equals(brandId)) {
                wrapper.eq("brand_id", brandId);
            }
        }
        String status = (String) params.get("status");
        if (StringUtils.isNotEmpty(status)) {
            if (!"0".equals(status)) {
                wrapper.eq("publish_status", status);
            }
        }


        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void up(Long spuId) {
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.queryProductAttrValue(spuId);
        List<Long> attrIds = productAttrValueEntities.stream().map(productAttrValueEntity -> {
            return productAttrValueEntity.getAttrId();
        }).collect(Collectors.toList());
        List<Long> searchAttrIds = attrService.getSearchAttrIds(attrIds);

        List<SkuEsModel.Attr> attrs = productAttrValueEntities.stream().filter(productAttrValueEntity -> {
            return searchAttrIds.contains(productAttrValueEntity.getAttrId());
        }).map(productAttrValueEntity -> {
            SkuEsModel.Attr attr = new SkuEsModel.Attr();
            BeanUtils.copyProperties(productAttrValueEntity, attr);

            return attr;
        }).collect(Collectors.toList());



        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkusBySpuId(spuId);
        List<Long> skuIds = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());

        Map<Long, Boolean> hasStockMap = null;
        try {
            R skusHasStock = wareFeignService.getSkusHasStock(skuIds);
            Object data = skusHasStock.get("data");
            String dataJsonString = JSON.toJSONString(data);
            JSONArray jsonArray = JSONArray.parseArray(dataJsonString);
            List<SkuHasStockTo> hasStock = jsonArray.toJavaList(SkuHasStockTo.class);

            hasStockMap = hasStock.stream().collect(Collectors.toMap(SkuHasStockTo::getSkuId, item -> item.isHasStock()));
        } catch (Exception e) {
            log.error("库存服务查询异常{}", e);
        }

        Map<Long, Boolean> finalHasStockMap = hasStockMap;
        List<SkuEsModel> skuEsModels = skuInfoEntities.stream().map(skuInfoEntity -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(skuInfoEntity, skuEsModel);

            skuEsModel.setSkuPrice(skuInfoEntity.getPrice());
            skuEsModel.setSkuImg(skuInfoEntity.getSkuDefaultImg());

            BrandEntity brandEntity = brandService.getById(skuEsModel.getBrandId());
            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());

            CategoryEntity categoryEntity = categoryService.getById(skuInfoEntity.getCatalogId());
            skuEsModel.setCatelogName(categoryEntity.getName());

            skuEsModel.setAttrs(attrs);

            skuEsModel.setHotScore(0L);

            if (finalHasStockMap == null) {
                skuEsModel.setHasStock(true);
            } else {
                skuEsModel.setHasStock(finalHasStockMap.get(skuInfoEntity.getSkuId()));
            }


            return skuEsModel;
        }).collect(Collectors.toList());

        R r = searchFeignService.productStatusUp(skuEsModels);
        if (r.getCode() != 0) {
            log.error("远程调用ElasticSearch的商品上架服务失败");
        } else {
            baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.ATTR_TYPE_UP.getCode());
        }

        System.out.println(skuEsModels);
    }

    @Override
    public SpuInfoEntity getSpuInfo(Long skuId) {
        SkuInfoEntity skuInfo = skuInfoService.getById(skuId);
        Long spuId = skuInfo.getSpuId();
        SpuInfoEntity spuInfo = this.getById(spuId);

        return spuInfo;
    }
}